﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TvViewer.MpTvService;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
using MediaPortal.TvServer.WebServices;
using System.Configuration;
using Gma.UserActivityMonitor;
using System.Reflection;
using Vlc.DotNet.Core.Medias;
using System.Diagnostics;

namespace TvViewer
{
  public partial class MainForm : Form
  {
    #region privates/enums
    private const string TITLE_TEXT = "Watch TV on your Desktop";
    private String m_currentMenuTitle;

    private enum ViewMode { Minimalistic, Compact, Normal }
    private enum TopMode { Never, Always, WhilePlaying }
    private enum StreamMode { RTSP, Direct, Transcoded }

    ServiceInterface m_server;
    WebChannel[] m_channels;
    object m_lockObject = new object();
    WebChannelGroup[] m_groups;
    WebMiniEPG[] m_programGuides;
    bool m_tvPlaying = false;
    bool m_mediaPlaying = false;
    ViewMode m_viewMode = ViewMode.Normal;
    TopMode m_topMode = TopMode.Never;
    StreamMode m_streamMode = StreamMode.RTSP;
    WebTvServerUser m_currentUser;
    private int m_selectedChannelIndex = -1;
    private DateTime m_timeShiftingStart;
    private long m_lastTimePosChanged = -1;//the time at which the user actually set the position
    private long m_timeOfLastPos = -1;//the time within the timeshift buffer to which the last position was set
    private long m_timeOfLastPause = -1;////the time at which the user last pressed pause
    private long m_timeTvWasPaused = 0;

    private float m_videoPosition = 0;
    private bool m_sliderIsSelecting = false;

    private Size m_lastSizeForm;
    private Size m_lastSizeVlc;

    private Point oldLocation;
    private Point oldCursor;

    private bool m_showAllGroup = false;
    private String m_defaultGroup = null;
    private bool m_useInternalVlcPlayer;
    private String m_externalVlcPath;

    private String m_deinterlaceMode;
    private int m_rtspBuffering;

    private bool m_autoTune;//automatically tune channel on selection

    #endregion

    public MainForm()
    {
      InitializeComponent();
      HookManager.MouseDown += HookManager_MouseDown;
      HookManager.MouseUp += HookManager_MouseUp;
    }

    ~MainForm()
    {
      HookManager.MouseDown -= HookManager_MouseDown;
      HookManager.MouseUp -= HookManager_MouseUp;
    }


    private void MainForm_Load(object sender, EventArgs e)
    {
       // Util.ChangeSettingsValue("TvViewer.exe.config", "UseInternalVlc", "False");
      InitialiseViewer();
      InitialiseVlcControl();
      
    }

    private void InitialiseVlcControl()
    {
      try
      {
        if (m_useInternalVlcPlayer)
        {//use the vlc dll's that come distributed with the (full) install.
          vlcPlayerControl.Manager.VlcLibPath = Path.Combine(GetStartupPath(), "libvlc");
        }
        else
        {
          vlcPlayerControl.Manager.VlcLibPath = m_externalVlcPath;
        }

        List<string> options = new List<string>();
        options.Add(":no-one-instance");
        options.Add(":no-loop");
        options.Add(":disable-screensaver");

        if (m_rtspBuffering > 0)
        {
          options.Add(":realrtsp-caching=" + m_rtspBuffering);
        }

        if (!m_deinterlaceMode.Equals("Disabled"))
        {
          options.Add("--vout-filter=deinterlace");
          options.Add("--deinterlace-mode=" + m_deinterlaceMode.ToLower());
          //MessageBox.Show("Set deinterlace mode: " + m_deinterlaceMode.ToLower()); 
        }

        vlcPlayerControl.Manager.Initialise(options);
        tbVolume.Value = Properties.Settings.Default.DefaultVolume;
        vlcPlayerControl.Manager.Volume = Properties.Settings.Default.DefaultVolume;
        vlcPlayerControl.Manager.PropertyChanged += new PropertyChangedEventHandler(Manager_PropertyChanged);
      }
      catch (Exception ex)
      {
        MessageBox.Show("Couldn't initialise VLC player");
      }
    }

    void Manager_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      //Console.WriteLine(e.PropertyName);
    }

    private void DeinitialiseVlcControl()
    {

      if (m_mediaPlaying)
      {
        StopPlayback();
      }
    }

    private static string GetStartupPath()
    {
      return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    }

    private void InitialiseViewer()
    {
      try
      {
        m_autoTune = false;

        if (Properties.Settings.Default.FirstTime)
        {//first start
          OptionsForm frm = new OptionsForm();
          if (frm.ShowDialog() != DialogResult.OK)
          {
            Application.Exit();
          }
        }

        m_defaultGroup = Properties.Settings.Default.DefaultGroup;
        m_showAllGroup = Properties.Settings.Default.ShowAllGroup;
        m_rtspBuffering = Properties.Settings.Default.RtspBuffering;
        m_deinterlaceMode = Properties.Settings.Default.DeinterlaceMode;
        m_externalVlcPath = Properties.Settings.Default.ExternalVlcPath;
        m_useInternalVlcPlayer = Properties.Settings.Default.UseInternalVlc;
        cbAutoTune.Checked = Properties.Settings.Default.TvAutoStart;
        m_server = new ServiceInterface();
        SupportedMPFunctions f = m_server.GetSupportedMPFunctions();

        m_groups = m_server.GetTvChannelGroups();
      }
      catch (Exception ex)
      {
        MessageBox.Show("Couldn't connect to webservice, verify your settings");
        return;
      }


      cbGroups.Items.Clear();
      if (m_groups != null)
      {
        for (int i = 0; i < m_groups.Length; i++)// (WebChannelGroup c in groups)
        {
          if (m_groups[i].idGroup != 1 || m_showAllGroup)
          {
            cbGroups.Items.Add(m_groups[i].name);
            if (m_groups[i].name.Equals(m_defaultGroup))
            {
              cbGroups.SelectedIndex = cbGroups.Items.Count - 1;
            }
          }
        }
      }

      SetVlcControlsEnabled(false);
      timerUpdateEpg.Enabled = true;
      m_autoTune = true;
    }

    private void cbGroups_SelectedIndexChanged(object sender, EventArgs e)
    {
      m_autoTune = false;
      UpdateEPG();
      FillChannelsDropDownList();
      if (cbChannels.Items.Count > 0)
      {
        cbChannels.SelectedIndex = 0;
      }
      m_autoTune = true;
    }

    private void cbChannels_DropDown(object sender, EventArgs e)
    {
      FillChannelsDropDownList();
    }

    private void FillChannelsDropDownList()
    {
      try
      {
        lock (m_lockObject)
        {
          int index = m_showAllGroup ? cbGroups.SelectedIndex : cbGroups.SelectedIndex + 1;
          WebChannelGroup selectedChannel = m_groups[index];

          m_channels = m_server.GetChannelsInTvGroup(selectedChannel.idGroup);
          cbChannels.Items.Clear();
          channelsToolStripMenuItem.DropDownItems.Clear();

          for (int i = 0; i < m_channels.Length; i++)
          {
            String itemText = m_channels[i].displayName;
            if (m_programGuides != null && m_programGuides[i] != null)
            {
              WebShortProgram cur = m_programGuides[i].epgNow;
              double length = (cur.endTime - cur.startTime).TotalSeconds;
              double passed = (DateTime.Now - cur.startTime).TotalSeconds;
              double perc = passed / length * 100;
              String percString = " (" + ((int)perc).ToString() + "% )";
              if (perc < 0 || perc > 150)
              {
                percString = "( -- )";
              }
              itemText += " - " + cur.title + percString;
            }
            cbChannels.Items.Add(itemText);

            ToolStripMenuItem item = channelsToolStripMenuItem.DropDownItems.Add(itemText) as ToolStripMenuItem;
            if (m_currentUser != null && m_currentUser.idChannel == m_channels[i].idChannel)
            {
              item.Checked = true;
            }
            else
            {
              item.Checked = false;
            }
            item.Tag = i;
            item.Click += channelToolStripItem_Click;
          }
        }
      }
      catch (Exception ex)
      {
        lblStatusText.Text = ("Couldn't retrieve details from webservices (" +  DateTime.Now.ToShortTimeString() + ")");
      }
    }

    private void UpdateEPG()
    {
      try
      {
        lock (m_lockObject)
        {
          //lblStatusText.Text = "Update EPG (" + DateTime.Now.ToLongTimeString() + ")";

          int index = m_showAllGroup ? cbGroups.SelectedIndex : cbGroups.SelectedIndex + 1;
          WebChannelGroup selectedGroup = m_groups[index];

          m_programGuides = m_server.GetTvMiniEPGForGroup(selectedGroup.idGroup);

          if (m_selectedChannelIndex != -1)
          {//Update epgnow and epgnext textboxes
            UpdateMiniEPG(m_selectedChannelIndex);
          }
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("Couldn't update epg");
      }
    }

    private void UpdateMiniEPG(int _selectedChannelIndex)
    {
      if (_selectedChannelIndex != -1 && m_programGuides != null && m_programGuides[_selectedChannelIndex] != null)
      {
        WebMiniEPG epg = m_programGuides[_selectedChannelIndex];
        txtEpgNow.Text = epg.epgNow.title + " (" + epg.epgNow.startTime.ToShortTimeString() +
                         " - " + epg.epgNow.endTime.ToShortTimeString() + ")";
        txtEpgNext.Text = epg.epgNext.title + " (" + epg.epgNext.startTime.ToShortTimeString() +
                   " - " + epg.epgNext.endTime.ToShortTimeString() + ")";
      }
    }

    void channelToolStripItem_Click(object sender, EventArgs e)
    {
      ToolStripItem item = sender as ToolStripItem;
      m_selectedChannelIndex = (int)item.Tag;
      SelectChannel(m_selectedChannelIndex, true);
    }

    private void SelectChannel(int _index, bool _autoStart)
    {
      UpdateMiniEPG(_index);
      WebChannel selectedChannel = m_channels[_index];

      if (m_currentUser == null || selectedChannel.idChannel != m_currentUser.idChannel)
      {//we switched to a new channel (not same channel as playing)
        if (_autoStart)
        {//start playback
          if (m_mediaPlaying)
          {
            StopPlayback();
          }
          PlayChannel(selectedChannel);
        }
      }
    }



    private void cbChannels_SelectedIndexChanged(object sender, EventArgs e)
    {
      m_selectedChannelIndex = cbChannels.SelectedIndex;
      SelectChannel(m_selectedChannelIndex, m_autoTune && cbAutoTune.Checked);
    }

    private void PlayChannel(WebChannel _channel)
    {
      try
      {
        WebTvResult t = m_server.StartTimeShifting(_channel.idChannel);

        if (t.result == 0)
        {
          m_timeShiftingStart = DateTime.Now;
          m_lastTimePosChanged = -1;
          m_timeOfLastPos = -1;
          m_timeTvWasPaused += 0;
          m_timeOfLastPause = -1;


          cmdStartPlaying.Text = "Stop Playing";
          stopToolStripMenuItem.Text = "Stop";
          String url = t.rtspURL;
          m_currentUser = t.user;

          SetMenuTitle(TITLE_TEXT + " - " + _channel.displayName);
          SetVlcControlsEnabled(true);
          //SetPositioningControlsEnabled(false);
          sliderVideoPosition.Value = 100;
          m_videoPosition = 1;

          CustomMedia media = new CustomMedia(url);
          vlcPlayerControl.Manager.MediaLibrary.SelectedMedia = media;
          vlcPlayerControl.Manager.Play(media);
          m_tvPlaying = true;
          m_mediaPlaying = true;
          if (m_topMode == TopMode.WhilePlaying)
          {
            this.TopMost = true;
          }
          lblStatusText.Text = "Play channel " + _channel.displayName;
          timerVlcTimer.Start();
        }
        else
        {
          MessageBox.Show("Couldn't start timeshift");
          lblStatusText.Text = "Error switching to channel " + _channel.displayName;
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show("Error while start timeshifting");
      }
    }

    private void SetMenuTitle(string _title)
    {
      m_currentMenuTitle = _title;
      if (m_viewMode != ViewMode.Minimalistic)
      {
        this.Text = m_currentMenuTitle;
      }
    }

    private void StopPlayback()
    {
      cmdStartPlaying.Text = "Start Playing";
      stopToolStripMenuItem.Text = "Start";
      vlcPlayerControl.Manager.Stop();
      m_mediaPlaying = false;
      SetMenuTitle(TITLE_TEXT);
      SetVlcControlsEnabled(false);
      timerVlcTimer.Stop();
      if (m_tvPlaying)
      {
        bool success;
        try
        {
          success = m_server.StopTimeShifting(m_currentUser.idChannel, m_currentUser.idCard, m_currentUser.name);
        }
        catch (Exception)
        {
          success = false;
        }

        if (success)
        {
          m_currentUser = null;
          m_tvPlaying = false;
          if (m_topMode == TopMode.WhilePlaying)
          {
            this.TopMost = false;
          }
        }
        else
        {
          MessageBox.Show("Couldn't stop timeshift");
        }
      }
    }

    private void PauseResumePlayback()
    {
      if (vlcPlayerControl.Manager.State == Vlc.DotNet.Core.Interop.VlcState.Playing)
      {
        vlcPlayerControl.Manager.Pause();
        lblStatusText.Text = "Paused Playback";
        cmdPauseResume.Text = "Resume";
        pauseToolStripMenuItem.Text = "Resume";
        if (m_tvPlaying)
        {
          m_timeOfLastPause = DateTime.Now.Ticks;
        }
      }
      else
      {
        if (m_tvPlaying)
        {
          m_timeTvWasPaused += (DateTime.Now.Ticks - m_timeOfLastPause);//add the time tv was paused to total amount of paused time
          m_timeOfLastPause = -1;//
        }
        vlcPlayerControl.Manager.Pause();
        lblStatusText.Text = "Resumed Playback";
        cmdPauseResume.Text = "Pause";
        pauseToolStripMenuItem.Text = "Pause";
      }
    }

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
      if (m_tvPlaying)
      {
        try
        {
          m_server.StopTimeShifting(m_currentUser.idChannel, m_currentUser.idCard, m_currentUser.name);
          DeinitialiseVlcControl();
        }
        catch (Exception) { }
      }
    }

    private void SetViewMode(ViewMode _viewMode)
    {
      Console.WriteLine("Set view mode: " + _viewMode.ToString());

      if (m_viewMode == ViewMode.Normal)
      {//save last known size
        m_lastSizeForm = this.Size;
        m_lastSizeVlc = vlcPlayerControl.Size;
      }

      m_viewMode = _viewMode;

      if (_viewMode == ViewMode.Minimalistic)
      {//tv window and title bar
        SetMenuItemsVisible(false);
        this.Text = String.Empty;
        this.ControlBox = false;
        this.Height = vlcPlayerControl.Height + 7;
        this.Width = vlcPlayerControl.Width;
        vlcPlayerControl.Dock = DockStyle.Fill;
      }
      else if (_viewMode == ViewMode.Compact)
      {//only tv window
        SetMenuItemsVisible(false);
        this.ControlBox = true;
        this.Text = m_currentMenuTitle;
        this.Height = vlcPlayerControl.Height + SystemInformation.CaptionHeight + 7;
        this.Width = vlcPlayerControl.Width;
        vlcPlayerControl.Dock = DockStyle.Fill;
      }
      else
      {//normal
        this.ControlBox = true;
        this.Text = m_currentMenuTitle;
        this.Size = m_lastSizeForm;
        vlcPlayerControl.Dock = DockStyle.None;
        vlcPlayerControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
        vlcPlayerControl.Size = m_lastSizeVlc;
        SetMenuItemsVisible(true);
      }
    }

    private void SetMenuItemsVisible(bool _visible)
    {
      menuStripMain.Visible = _visible;
      cmdStartPlaying.Visible = _visible;
      lblEpgNow.Visible = _visible;
      lblEpgNext.Visible = _visible;
      txtEpgNext.Visible = _visible;
      txtEpgNow.Visible = _visible;
      cbChannels.Visible = _visible;
      cbGroups.Visible = _visible;
      cbAutoTune.Visible = _visible;

      cmdBeginning.Visible = _visible;
      cmdPrevious.Visible = _visible;
      cmdPauseResume.Visible = _visible;
      cmdForward.Visible = _visible;
      cmdLast.Visible = _visible;
      tbVolume.Visible = _visible;
      statusStripMain.Visible = _visible;
      sliderVideoPosition.Visible = _visible;
      lblVolume.Visible = _visible;
      txtCurrentPosTime.Visible = _visible;
      txtCurrentPosAbs.Visible = _visible;
    }

    /// <summary>
    /// Sets enabled state of all vlc control button 
    /// </summary>
    /// <param name="_enabled">enabled or disabled</param>
    private void SetVlcControlsEnabled(bool _enabled)
    {
      cmdBeginning.Enabled = _enabled;
      cmdPrevious.Enabled = _enabled;
      cmdForward.Enabled = _enabled;
      cmdLast.Enabled = _enabled;
      cmdPauseResume.Enabled = _enabled;
      tbVolume.Enabled = _enabled;
      sliderVideoPosition.Enabled = _enabled;
      txtCurrentPosTime.Enabled = _enabled;
      txtCurrentPosAbs.Enabled = _enabled;
    }

    /// <summary>
    /// only set state of positioning controls (back, forward)
    /// </summary>
    /// <param name="_enabled">enabled or disabled</param>
    private void SetPositioningControlsEnabled(bool _enabled)
    {
      cmdBeginning.Enabled = _enabled;
      cmdPrevious.Enabled = _enabled;
      cmdForward.Enabled = _enabled;
      cmdLast.Enabled = _enabled;
    }

    private void SetTopMode(TopMode _topMode)
    {
      lblStatusText.Text = "Set top mode: " + _topMode.ToString();
      m_topMode = _topMode;
      alwaysToolStripMenuItem.Checked = false;
      neverToolStripMenuItem.Checked = false;
      whilePlayingToolStripMenuItem.Checked = false;
      switch (_topMode)
      {
        case TopMode.Always:
          alwaysToolStripMenuItem.Checked = true;
          this.TopMost = true;
          break;
        case TopMode.Never:
          neverToolStripMenuItem.Checked = true;
          this.TopMost = false;
          break;
        case TopMode.WhilePlaying:
          whilePlayingToolStripMenuItem.Checked = true;
          this.TopMost = m_tvPlaying;
          break;
      }
    }

    private void SetVideoPosition(float _position)
    {
      if (m_mediaPlaying)
      {
        if (m_tvPlaying)
        {
          m_timeOfLastPause = -1;
          m_timeTvWasPaused = 0;
          m_lastTimePosChanged = DateTime.Now.Ticks;
          m_timeOfLastPos = (long)((DateTime.Now.Ticks - m_timeShiftingStart.Ticks) * _position);
        }
        lblStatusText.Text = "Change position to " + _position;
        if (!m_tvPlaying && _position >= 0.995f) _position = 0.995f;//set position to 99% if we're playing a file 
        vlcPlayerControl.Manager.Position = _position;
        m_videoPosition = _position;
        sliderVideoPosition.Value = (int)(_position * 100f);
      }
    }

    private void SetVolume(int _volume)
    {
      if (m_mediaPlaying)
      {
        vlcPlayerControl.Manager.Volume = _volume;
        lblStatusText.Text = "Volume: " + _volume.ToString() + " %";
      }
    }

    private void ShowOptions()
    {
      OptionsForm frm = new OptionsForm();
      if (frm.ShowDialog() == DialogResult.OK)
      {
        if (!m_deinterlaceMode.Equals(Properties.Settings.Default.DeinterlaceMode)
            || m_rtspBuffering != Properties.Settings.Default.RtspBuffering
            || m_useInternalVlcPlayer != Properties.Settings.Default.UseInternalVlc
            || !m_useInternalVlcPlayer && (m_externalVlcPath != Properties.Settings.Default.ExternalVlcPath))
        {//Changes in vlc player -> reset player
          StopPlayback();
          DeinitialiseVlcControl();
          Application.Restart();
        }
        else
        {
          InitialiseViewer();//to reflect changes
        }
      }
    }

    private void OpenLocalFile()
    {
      OpenFileDialog openFile = new OpenFileDialog();
      if (openFile.ShowDialog() == DialogResult.OK)
      {
        FileMedia input = new FileMedia(openFile.FileName);
        vlcPlayerControl.Manager.MediaLibrary.MediaItems.Add(input);
        vlcPlayerControl.Manager.MediaLibrary.SelectedMedia = input;
        vlcPlayerControl.Manager.Play(input);
        cmdStartPlaying.Text = "Stop Playing";
        SetVlcControlsEnabled(true);
        timerVlcTimer.Start();
        m_currentMenuTitle = TITLE_TEXT + " - " + openFile.FileName;
        this.Text = m_currentMenuTitle;

        m_tvPlaying = false;
        m_mediaPlaying = true;
        m_videoPosition = 0;
        sliderVideoPosition.Value = 0;
      }
    }

    private void ShowTvGuide()
    {
      int index = m_showAllGroup ? cbGroups.SelectedIndex : cbGroups.SelectedIndex + 1;
      WebChannelGroup selectedChannel = m_groups[index];
      EpgForm frmEpg = new EpgForm(m_server, selectedChannel);
      frmEpg.Show();
    }

    private void ShowServerStatus()
    {
      ServerStatusForm statusForm = new ServerStatusForm(m_server);
      statusForm.Show();
    }

    private void ShowAboutForm()
    {
      AboutForm aboutForm = new AboutForm();
      aboutForm.ShowDialog(this);
    }

    private void ShowScheduleForm()
    {
      SchedulesForm frm = new SchedulesForm(m_server);
      frm.Show();
    }

    #region form dragging
    private bool m_dragEnabled = false;
    private void timerPlayerMove_Tick(object sender, EventArgs e)
    {
      if (m_dragEnabled)
      {
        int newX = oldLocation.X - oldCursor.X + System.Windows.Forms.Cursor.Position.X;
        int newY = oldLocation.Y - oldCursor.Y + System.Windows.Forms.Cursor.Position.Y;
        this.Location = new Point(newX, newY);
      }
    }

    private void StartStopTvPlayback()
    {
      try
      {
        if (!m_mediaPlaying)
        {
          WebChannel selectedChannel = m_channels[m_selectedChannelIndex];
          PlayChannel(selectedChannel);
        }
        else
        {
          StopPlayback();
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show("Error during start/stop timeshift");
      }
    }

    void HookManager_MouseUp(object sender, MouseEventArgs e)
    {
      Point cursor = System.Windows.Forms.Cursor.Position;
      if (e.Button == MouseButtons.Left)
      {
        if (m_dragEnabled)
        {//we want to drag
          timerPlayerMove.Stop();
          m_dragEnabled = false;
        }

        if (cmVlcPlayer.Visible)
        {

          if (!Intersects(cmVlcPlayer.ClientRectangle, cmVlcPlayer.PointToClient(cursor)))
          {
            bool intersects = false;
            if (channelsToolStripMenuItem.IsOnDropDown)
            {
              foreach (ToolStripItem i in channelsToolStripMenuItem.DropDownItems)
              {
                if (i.Selected)
                {
                  intersects = true;
                  break;
                }
              }
            }
            if (!intersects) cmVlcPlayer.Hide();
          }
        }

      }

      if (e.Button == MouseButtons.Right)
      {
        if (m_mediaPlaying)
        {
          if (Intersects(new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height)
             , cursor))
          {
            cmVlcPlayer.Show(vlcPlayerControl, vlcPlayerControl.PointToClient(cursor));
          }
        }
      }
    }

    void HookManager_MouseDown(object sender, MouseEventArgs e)
    {
      if (m_viewMode == ViewMode.Minimalistic && e.Button == MouseButtons.Left)
      {
        Point cursor = System.Windows.Forms.Cursor.Position;
        if (Intersects(new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height)
                       , cursor))
        {
          m_dragEnabled = true;
          oldLocation = this.Location;
          oldCursor = System.Windows.Forms.Cursor.Position;
          timerPlayerMove.Start();
        }
      }
    }

    private bool Intersects(Rectangle _rect, Point _point)
    {
      if (_rect.X + 10 < _point.X &&
          _rect.X + _rect.Width - 10 > _point.X &&
          _rect.Y + 10 < _point.Y &&
          _rect.Y + _rect.Height - 10 > _point.Y)
      {
        return true;
      }
      else
      {
        return false;
      }
    }


    #endregion

    #region keypresses
    private void MainForm_KeyUp(object sender, KeyEventArgs e)
    {
      if (m_viewMode != ViewMode.Normal && e.KeyCode == Keys.Escape)
      {
        SetViewMode(ViewMode.Normal);
      }

      if (e.KeyCode == Keys.NumPad1 || e.KeyCode == Keys.D1)
      {
        SetViewMode(ViewMode.Minimalistic);
      }

      if (e.KeyCode == Keys.NumPad2 || e.KeyCode == Keys.D2)
      {
        SetViewMode(ViewMode.Compact);
      }

      if (e.KeyCode == Keys.NumPad3 || e.KeyCode == Keys.D3)
      {
        SetViewMode(ViewMode.Normal);
      }

      if (e.KeyCode == Keys.A && e.Modifiers == Keys.Control)
      {
        SetTopMode(TopMode.Always);
      }

      if (e.KeyCode == Keys.W && e.Modifiers == Keys.Control)
      {
        SetTopMode(TopMode.WhilePlaying);
      }

      if (e.KeyCode == Keys.N && e.Modifiers == Keys.Control)
      {
        SetTopMode(TopMode.Never);
      }

      if (e.KeyCode == Keys.B)
      {
        if (m_mediaPlaying)
        {
          StopPlayback();
        }
      }

      if (e.KeyCode == Keys.Space)
      {
        if (m_mediaPlaying)
        {
          PauseResumePlayback();
        }
      }


      if (e.KeyCode == Keys.T)
      {
        //todo: implement teletext -> not working with libvlc 1.0
        if (m_tvPlaying)
        {
          //Console.WriteLine("Toogle teletext");
          //vlcPlayerControl.Manager.ToogleTeletext();
          //vlcPlayerControl.Manager.SetTeletextPage(200);
        }
      }

      if (e.KeyCode == Keys.Up)
      {
        SetVideoPosition(1);
      }

      if (e.KeyCode == Keys.Down)
      {
        SetVideoPosition(0);
      }

      if (e.KeyCode == Keys.Left)
      {
        SetVideoPosition(m_videoPosition - 0.1f);
      }

      if (e.KeyCode == Keys.Right)
      {
        SetVideoPosition(m_videoPosition + 0.1f);
      }

      if (cbChannels.Focused)
      {
        e.Handled = true;
      }
    }
    #endregion

    #region menus

    private void minimalisticPress1ToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetViewMode(ViewMode.Minimalistic);
    }

    private void compactPress2ToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetViewMode(ViewMode.Compact);
    }

    private void normalPress3ToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetViewMode(ViewMode.Normal);
    }

    private void whilePlayingToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetTopMode(TopMode.WhilePlaying);
    }

    private void alwaysToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetTopMode(TopMode.Always);
    }

    private void neverToolStripMenuItem_Click(object sender, EventArgs e)
    {
      SetTopMode(TopMode.Never);
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ShowAboutForm();
    }

    private void cmdPauseResume_Click(object sender, EventArgs e)
    {
      PauseResumePlayback();
    }

    private void cmdBeginning_Click(object sender, EventArgs e)
    {
      SetVideoPosition(0);
    }

    private void cmdPrevious_Click(object sender, EventArgs e)
    {
      if (m_tvPlaying)
      {
        float curPos = (float)(vlcPlayerControl.Manager.Time.TotalMilliseconds / vlcPlayerControl.Manager.Length.TotalMilliseconds);
        SetVideoPosition(curPos - 0.1f);
      }
      else
      {
        SetVideoPosition(m_videoPosition - 0.1f);
      }
    }

    private void cmdForward_Click(object sender, EventArgs e)
    {
      if (m_tvPlaying)
      {
        float curPos = (float)(vlcPlayerControl.Manager.Time.TotalMilliseconds / vlcPlayerControl.Manager.Length.TotalMilliseconds);
        SetVideoPosition(curPos + 0.1f);
      }
      else
      {
        SetVideoPosition(m_videoPosition + 0.1f);
      }
    }

    private void cmdLast_Click(object sender, EventArgs e)
    {
      SetVideoPosition(1);
    }


    private void tbVolume_Scroll(object sender, EventArgs e)
    {
      SetVolume(tbVolume.Value);
    }

    private void serverStatusToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ShowServerStatus();
    }

    private void tVGuideToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ShowTvGuide();
    }

    private void openFileToolStripMenuItem_Click(object sender, EventArgs e)
    {
      OpenLocalFile();
    }

    private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ShowOptions();
    }

    private void scheduledRecordingsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ShowScheduleForm();
    }

    private void sliderVideoPosition_MouseUp(object sender, MouseEventArgs e)
    {
      SetVideoPosition((float)(sliderVideoPosition.Value / 100f));
      m_sliderIsSelecting = false;
    }

    private void sliderVideoPosition_MouseDown(object sender, MouseEventArgs e)
    {
      m_sliderIsSelecting = true;
    }

    private void timeUpdateSlider_Tick(object sender, EventArgs e)
    {

    }

    private void stopToolStripMenuItem_Click(object sender, EventArgs e)
    {
      StartStopTvPlayback();
    }



    private void pauseToolStripMenuItem_Click(object sender, EventArgs e)
    {
      PauseResumePlayback();
    }

    private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void cmVlcPlayer_Opening(object sender, CancelEventArgs e)
    {
      stopToolStripMenuItem.Enabled = m_mediaPlaying || m_selectedChannelIndex != -1;
      pauseToolStripMenuItem.Enabled = m_mediaPlaying;
      channelsToolStripMenuItem.Enabled = (channelsToolStripMenuItem.DropDownItems != null &&
                                           channelsToolStripMenuItem.DropDownItems.Count > 0);
    }

    private void timerUpdateEpg_Tick(object sender, EventArgs e)
    {
      UpdateEPG();
    }

    private void channelsToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
    {
      FillChannelsDropDownList();
    }

    private void cmdStartPlaying_Click(object sender, EventArgs e)
    {
      StartStopTvPlayback();
    }

    private void connectToolStripMenuItem_Click(object sender, EventArgs e)
    {
      InitialiseViewer();
    }

    #endregion

    #region Update positioning data
    private void timerVlcTimer_Tick(object sender, EventArgs e)
    {
      if (m_mediaPlaying)
      {
        if (!m_tvPlaying && !m_sliderIsSelecting)
        {//don't update when user is currently adjusting slider
          double perc = vlcPlayerControl.Manager.Time.TotalMilliseconds * 100 / vlcPlayerControl.Manager.Length.TotalMilliseconds;
          sliderVideoPosition.Value = (int)(perc);
        }

        if (m_tvPlaying)
        {//live tv
          long timeTvWasPaused = m_timeTvWasPaused;//the difference 

          if (m_timeOfLastPause != -1)
          {
            timeTvWasPaused += (DateTime.Now.Ticks - m_timeOfLastPause);
          }

          timeTvWasPaused *= -1;//negate so we can subtract it
          //lblStatusText.Text = new TimeSpan(timeTvWasPaused).TotalSeconds.ToString();
          long now = DateTime.Now.Ticks;
          if (m_videoPosition == 1)
          {//we're at the current time (now) / never changed the position within the stream
            txtCurrentPosTime.Text = DateTime.Now.AddTicks(timeTvWasPaused).ToLongTimeString();
            TimeSpan ellapsed = new TimeSpan(now - m_timeShiftingStart.Ticks + timeTvWasPaused);

            txtCurrentPosAbs.Text = (int)ellapsed.TotalMinutes + ":" + (int)ellapsed.Seconds;
          }
          else
          {
            long start = m_timeShiftingStart.Ticks;
            long curPos = m_timeOfLastPos + (now - m_lastTimePosChanged);
            txtCurrentPosTime.Text = new DateTime(start + curPos + timeTvWasPaused).ToLongTimeString();

            TimeSpan ellapsed = new TimeSpan(curPos + timeTvWasPaused);
            txtCurrentPosAbs.Text = (int)ellapsed.TotalMinutes + ":" + (int)ellapsed.Seconds; ;
          }
        }
      }
    }
    #endregion



  }
}
